package com.rongji.dfish.demo.editor.service.uiadaptor;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import com.rongji.dfish.base.Utils;
import com.rongji.dfish.base.util.BeanUtil;
import com.rongji.dfish.demo.entity.DfishViewNode;
import com.rongji.dfish.framework.ThreadLocalConstants;
import com.rongji.dfish.ui.Alignable;
import com.rongji.dfish.ui.Combo;
import com.rongji.dfish.ui.Command;
import com.rongji.dfish.ui.DataContainer;
import com.rongji.dfish.ui.DialogHeight;
import com.rongji.dfish.ui.DialogWidth;
import com.rongji.dfish.ui.EventTarget;
import com.rongji.dfish.ui.FormElement;
import com.rongji.dfish.ui.HiddenContainer;
import com.rongji.dfish.ui.JsonObject;
import com.rongji.dfish.ui.Layout;
import com.rongji.dfish.ui.Scrollable;
import com.rongji.dfish.ui.Valignable;
import com.rongji.dfish.ui.annotation.validation.Pattern;
import com.rongji.dfish.ui.command.SubmitCommand;
import com.rongji.dfish.ui.form.BoxField;
import com.rongji.dfish.ui.form.Checkbox;
import com.rongji.dfish.ui.form.ComboboxOption;
import com.rongji.dfish.ui.form.DatePicker;
import com.rongji.dfish.ui.form.Hidden;
import com.rongji.dfish.ui.form.LabelRow;
import com.rongji.dfish.ui.form.MuldatePicker;
import com.rongji.dfish.ui.form.Password;
import com.rongji.dfish.ui.form.Radio;
import com.rongji.dfish.ui.form.Select;
import com.rongji.dfish.ui.form.Text;
import com.rongji.dfish.ui.form.Textarea;
import com.rongji.dfish.ui.form.Triplebox;
import com.rongji.dfish.ui.form.UploadButton;
import com.rongji.dfish.ui.form.Validate;
import com.rongji.dfish.ui.helper.FormPanel;
import com.rongji.dfish.ui.helper.GridLayoutFormPanel;
import com.rongji.dfish.ui.helper.GridPanel;
import com.rongji.dfish.ui.helper.GroupingGridPanel;
import com.rongji.dfish.ui.helper.Label;
import com.rongji.dfish.ui.helper.StackPanel;
import com.rongji.dfish.ui.helper.TabPanel;
import com.rongji.dfish.ui.json.ClassJsonBuilder;
import com.rongji.dfish.ui.json.J;
import com.rongji.dfish.ui.json.JsonBuilder;
import com.rongji.dfish.ui.json.JsonBuilderProperGetter;
import com.rongji.dfish.ui.layout.ButtonBar;
import com.rongji.dfish.ui.layout.EmbedWindow;
import com.rongji.dfish.ui.layout.grid.AbstractGridLayout;
import com.rongji.dfish.ui.layout.grid.AbstractTd;
import com.rongji.dfish.ui.layout.grid.GridColumn;
import com.rongji.dfish.ui.layout.grid.GridLeaf;
import com.rongji.dfish.ui.layout.grid.Thead;
import com.rongji.dfish.ui.layout.grid.Tr;
import com.rongji.dfish.ui.widget.Button;
import com.rongji.dfish.ui.widget.CalendarCss;
import com.rongji.dfish.ui.widget.CalendarItem;
import com.rongji.dfish.ui.widget.CalendarPanel;
import com.rongji.dfish.ui.widget.DialogTemplate;
import com.rongji.dfish.ui.widget.Html;
import com.rongji.dfish.ui.widget.Img;
import com.rongji.dfish.ui.widget.Leaf;
import com.rongji.dfish.ui.widget.PageBar;
import com.rongji.dfish.ui.widget.Split;
import com.rongji.dfish.ui.widget.SubmitButton;
import com.rongji.dfish.ui.widget.TemplateTitle;
import com.rongji.dfish.ui.widget.TemplateView;
import com.rongji.dfish.ui.widget.Toggle;
import com.rongji.dfish.ui.widget.TreePanel;

/**
 * 管理器中管理基础信息的部分，包括原始本身的信息，字段，可以添加什么子字段，以及取得合适的适配器
 * @author LinLW
 *
 */
public class ComponentInfo{
	ComponentInfo(){
		
	}
	Map<String, TypeAdaptor> adaptors = new LinkedHashMap<String, TypeAdaptor>();
	Map<String, Class<?>> adaptorClass = new LinkedHashMap<String, Class<?>>();
//	Map<String,List<String>> accepts=new LinkedHashMap<String, List<String>>();
	/**
	 * 初始化方法，将所有符合适配器注册
	 */
	void init() {
		// FIXME 将所有的适配器注册
		List<Class<?>> uiClzes = getClassInFolderCascade(JsonObject.class);
		for (Class<?> clz : uiClzes) {
			if(!JsonObject.class.isAssignableFrom(clz)){
				continue;
			}
			if(clz.isInterface()
					||Modifier.isAbstract(clz.getModifiers())
					||!Modifier.isPublic(clz.getModifiers())){
				continue;
			}
			if(clz.getAnnotation(java.lang.Deprecated.class)!=null){
				continue;
			}
			if(clz.getName().indexOf('$')>=0){
				continue;
			}
//			if(HiddeneClass.class.isAssignableFrom(clz)){
//				continue;
//			}
			ComponentTypeAdaptor ada=new ComponentTypeAdaptor(clz);
			register(ada);
		}
		
		List<Object> instances = getInstancesInFolderCascade(TypeAdaptor.class);
		for (Object instance : instances) {
			if (instance instanceof TypeAdaptor) {
				register((TypeAdaptor) instance);
			}
		}
		
//		for(Map.Entry<String, Class<?>> entry:adaptorClass.entrySet()){
//			for(Map.Entry<String, Class<?>> subEntry:adaptorClass.entrySet()){
//				if(accept(entry.getValue(),subEntry.getValue())){
//					List<String> acc=accepts.get(entry.getKey());
//					if(acc==null){
//						acc=new ArrayList<String>();
//						accepts.put(entry.getKey(), acc);
//					}
//					acc.add(subEntry.getKey()); 
//				}
//			}
//		}

//		LOGGER.info(adaptorClass.keySet().toString());
	}
	private static final String LANG_FILE_PATH = "com.rongji.dfish.demo.editor.service.uiadaptor.componentinfo";
	/**
	 * 取得定制的语言
	 * 
	 * @param loc Locale 方言
	 * @param msgKey String 消息关键字
	 * @param args Object[]
	 * @return String
	 */
	public String getMsg(Locale loc, String msgKey, Object... args) {
		String value = null;
		try {
			ResourceBundle rb=ResourceBundle.getBundle(LANG_FILE_PATH, loc);
			if(rb==null){
				rb=ResourceBundle.getBundle(LANG_FILE_PATH, Locale.ENGLISH);
			}
			value = rb.getString(msgKey);
		} catch (MissingResourceException ex) {
			return msgKey;
		}
		if (args == null || args.length == 0) {
			return value;
		}
		return java.text.MessageFormat.format(value, args);
	}

	
	
	public String getCategoryName(String category){
		Locale loc=ThreadLocalConstants.LOCALE.get();
		if(loc==null){
			loc=Locale.getDefault();
		}
		return getMsg(loc,"cate."+category);
	}
	public String getPropName(String prop,String type){
		String key="prop."+prop+"."+type;  
		Locale loc=ThreadLocalConstants.LOCALE.get();
		if(loc==null){
			loc=Locale.getDefault();
		}
		String v=getMsg(loc,key);
		if(v.equals(key)){
			return getMsg(loc,"prop."+prop);
		}
		return v;
	}
	public String getPropTip(String prop,String type){
		String key="tip."+prop+"."+type;  
		Locale loc=ThreadLocalConstants.LOCALE.get();
		if(loc==null){
			loc=Locale.getDefault();
		}
		String v=getMsg(loc,key);
		if(v.equals(key)){
			v= getMsg(loc,"tip."+prop);
			if(v.equals("tip."+prop)){
				v=null;
			}
		}
		return v;
	}
	public String getConstName(String key){
		Locale loc=ThreadLocalConstants.LOCALE.get();
		if(loc==null){
			loc=Locale.getDefault();
		}
		return getMsg(loc,"cons."+key);
	}
	
	public String getCategory(Class<?> clz){
		if(clz==null){
			//should NOT happen!!!
			return "other";
		}
		if(TypeAdaptor.class.isAssignableFrom(clz)){
			if(StringAdaptor.class==clz){
				return "widget";
			}
			//FIXME gridLayoutFromPanel GridPanel
		}
		if(LabelRow.class.isAssignableFrom(clz)){
			if(Text.class==clz||Password.class==clz||Textarea.class==clz||Radio.class==clz||Checkbox.class==clz
					||Label.class==clz||Select.class==clz){
				return "form";
			}
			return "formx";
		}
		if(Command.class.isAssignableFrom(clz)){
			return "command";
		}
		if(Layout.class.isAssignableFrom(clz)){
			if(Tr.class==clz||AbstractTd.class==clz||GridColumn.class==clz||Thead.class==clz){
				return "grid";
			}else if(Button.class==clz||SubmitButton.class==clz||UploadButton.class==clz||Leaf.class==clz){
				return "widget";
			}else if(TreePanel.class==clz||ButtonBar.class==clz){
				return "panel";
			}else if(DialogTemplate.class==clz){
				return "template";
			}
			return "layout";
		}
		if(Hidden.class==clz){
			return "extra";
//		}else  if(Validate.class==clz){
//			return "extra";
		}else if(GridColumn.class==clz){
			return "grid"; //FIXME GridColumn
		}else if(Img.class==clz||GridLeaf.class==clz||Combo.class==clz||CalendarItem.class==clz||
				Toggle.class==clz||Split.class==clz||BoxField.class==clz||ComboboxOption.class==clz||
				CalendarCss.class==clz){
			return "widget";
		}else if(StackPanel.class==clz||TabPanel.class==clz){
			return "layout";
		}else if(Html.class==clz||FormPanel.class==clz||GridLayoutFormPanel.class==clz||GridPanel.class==clz||GroupingGridPanel.class==clz
				||PageBar.class==clz ||CalendarPanel.class==clz||EmbedWindow.class==clz){//FIXME PangePanel DateCalendarPanel 有误
			return "panel";
		}else if(TemplateTitle.class==clz||TemplateView.class==clz||DialogTemplate.class==clz){
			return "template";
		}
		
		return "other";
	}
	
	public String getTypeName(String type){
		Locale loc=ThreadLocalConstants.LOCALE.get();
		if(loc==null){
			loc=Locale.getDefault();
		}
		return getMsg(loc,"type."+type);
	}
	
//	@Deprecated
//	protected String convertType(Class<?> type){
//		return null;
//	}
	
//	protected Class<?> convertType(String type){
//		return this.;
//	}
	
//	public List<Class<?>> getAcceptClass(Class<?> clz){
//		return null;
//	}
	
//	public List<String> getAcceptType(String type) {
//		if(type==null||type.equals(null)){
//			return Arrays.asList("View");
//		}
//		return accepts.get(type);
//	}
//	
//	public Map<String, List<String>> getSpecialParts(String type) {
//		return getSpecialParts(adaptorClass.get(type));
//	}


	

	public String getCategory(String type) {
		return getCategory(adaptorClass.get(type));
	}
	/**
	 * 根据类获取此类同一目录和所有下级目录中类的实例
	 * @param clz 类
	 * @return 实例列表
	 */
	public List<Class<?>> getClassInFolderCascade(Class<?> clz) {
		List<Class<?>> result = new ArrayList<Class<?>>();
		String clzName = clz.getName();
		String packageName = clzName.substring(0, clzName.lastIndexOf('.'));
		String package2Path = packageName.replace('.', '/');

		URL path = clz.getResource(clzName.substring(clzName.lastIndexOf('.') + 1) + ".class");
		String protocol = path.getProtocol();
		
		if ("file".equals(protocol)) {
			File f = new File(path.getFile());
			File folder = f.getParentFile();
			File[] files = folder.listFiles();
			fillUIClass(result, packageName, files);
		} else if ("jar".equals(protocol)) {
			JarFile jar;
			try {
				jar = ((JarURLConnection) path.openConnection()).getJarFile();
				Enumeration<JarEntry> entries = jar.entries();
				while (entries.hasMoreElements()) {
					JarEntry entry = entries.nextElement();
					String name = entry.getName();
					if (!name.startsWith(package2Path) || entry.isDirectory()) {
						continue;
					}
					// 过滤 inner class
					if (name.indexOf('$') != -1) {
						continue;
					}
					String classSimpleName = name.substring(name.lastIndexOf('/') + 1);
					// 判定是否符合过滤条件
					String subName = classSimpleName.substring(0, classSimpleName.lastIndexOf('.'));
					try {
						result.add(Class.forName(packageName + "." + subName));
					} catch (Throwable t) {
						t.printStackTrace();
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}
	/**
	 * 填充适配器实例
	 * @param result 适配器列表
	 * @param packageName 类文件所在目录的目录路径(以.隔开)
	 * @param files 类文件
	 */
	private void fillUIClass(List<Class<?>> result, String packageName, File[] files) {
		if (result == null || files == null) {
			return;
		}
		for (File file : files) {
			if (file.isDirectory()) {
				fillUIClass(result, packageName + "." + file.getName(), file.listFiles());
			} else {
				String subName = file.getName().substring(0, file.getName().lastIndexOf('.'));
				try {
					result.add(Class.forName(packageName + "." + subName));
				} catch (Throwable t) {
					t.printStackTrace();
				}
			}
		}
	}

	
	public boolean hasDataProp(String nodeType) {
		return DataContainer.class.isAssignableFrom(this.adaptorClass.get(nodeType));//最新版本还有用处吗？
	}
	public boolean hasEventProp(String nodeType) {
		return EventTarget.class.isAssignableFrom(this.adaptorClass.get(nodeType));//最新版本还有用处吗？
	}
	public boolean hasHiddensProp(String nodeType) {
		return HiddenContainer.class.isAssignableFrom(this.adaptorClass.get(nodeType));//最新版本还有用处吗？
	}
//	/**
//	 * 判断这个控件是否有默认子节点。
//	 * @return
//	 */
//	public boolean isPubHolder(String nodeType){
//		return PubHolder.class.isAssignableFrom(this.adaptorClass.get(nodeType));//最新版本还有用处吗？
//	}
//	
//	/**
//	 * 如果这个控件有默认的子节点类型，返回子节点类型
//	 * @return
//	 */
//	public String getPubType(String nodeType){
////		@Override
////		public String getPubType() {
//			
//			return null;
////		}
//	}
	/**
	 * 填充适配器实例
	 * @param result 适配器列表
	 * @param packageName 类文件所在目录的目录路径(以.隔开)
	 * @param files 类文件
	 */
	private void fillAdaptorInstance(List<Object> result, String packageName, File[] files) {
		if (result == null || files == null) {
			return;
		}
		for (File file : files) {
			if (file.isDirectory()) {
				fillAdaptorInstance(result, packageName + "." + file.getName(), file.listFiles());
			} else {
				String subName = file.getName().substring(0, file.getName().lastIndexOf('.'));
				try {
					result.add(Class.forName(packageName + "." + subName).newInstance());
				} catch (Throwable t) {
//					t.printStackTrace();
				}
			}
		}
	}
	
	/**
	 * 根据适配器类型获取适配器
	 * @param typeName 适配器类型
	 * @return
	 */
	public TypeAdaptor getAdaptor(String typeName) {
		TypeAdaptor a= adaptors.get(typeName);
		return a;
	}
	/**
	 * 根据类获取此类同一目录和所有下级目录中类的实例
	 * @param clz 类
	 * @return 实例列表
	 */
	private List<Object> getInstancesInFolderCascade(Class<?> clz) {
		List<Object> result = new ArrayList<Object>();
		String clzName = clz.getName();
		String packageName = clzName.substring(0, clzName.lastIndexOf('.'));
		String package2Path = packageName.replace('.', '/');

		URL path = clz.getResource(clzName.substring(clzName.lastIndexOf('.') + 1) + ".class");
		String protocol = path.getProtocol();
		if ("file".equals(protocol)) {
			File f = new File(path.getFile());
			File folder = f.getParentFile();
			File[] files = folder.listFiles();
			fillAdaptorInstance(result, packageName, files);
		} else if ("jar".equals(protocol)) {
			JarFile jar;
			try {
				jar = ((JarURLConnection) path.openConnection()).getJarFile();
				Enumeration<JarEntry> entries = jar.entries();
				while (entries.hasMoreElements()) {
					JarEntry entry = entries.nextElement();
					String name = entry.getName();
					if (!name.startsWith(package2Path) || entry.isDirectory()) {
						continue;
					}
					// 过滤 inner class
					if (name.indexOf('$') != -1) {
						continue;
					}
					String classSimpleName = name.substring(name.lastIndexOf('/') + 1);
					// 判定是否符合过滤条件
					String subName = classSimpleName.substring(0, classSimpleName.lastIndexOf('.'));
					try {
						result.add(Class.forName(packageName + "." + subName).newInstance());
					} catch (Throwable t) {
						t.printStackTrace();
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}










	/**
	 * 注册适配器
	 * @param adaptor 适配器
	 */
	private void register(TypeAdaptor adaptor) {
		if (adaptor == null || Utils.isEmpty(adaptor.getTypeName())) {
			return;
		}
		if(adaptor instanceof ComponentTypeAdaptor){
			ComponentTypeAdaptor cast=(ComponentTypeAdaptor)adaptor;
			adaptorClass.put(adaptor.getTypeName(), cast.getClz());
		}else{
			adaptorClass.put(adaptor.getTypeName(), adaptor.getClass());
		}
		// 添加适配类
		adaptors.put(adaptor.getTypeName(), adaptor);
 	}
	private static final List<String> CATE_ORDER=Arrays.asList("widget","panel","layout","form","formx","grid","command","extra","other");
	public void sortCategory(List<String> category) {
		Collections.sort(category,CATE_ORDER_COMP);
	}
	public int  getTypeSortOrder(String type) {
		Class<?>clz=adaptorClass.get(type);
		if(clz==null){
			return 100;
		}
		if(Command.class.isAssignableFrom(clz)){
			return 50;
		}
		if(GridColumn.class==clz){
			return 70;
		}
		if(Validate.class==clz){
			return 70;
		}
		if(DialogTemplate.class==clz ){
			return 110;
		}

		return 100;
	}
	
	private static CateOrder CATE_ORDER_COMP=new CateOrder();
	private static class CateOrder implements java.util.Comparator<String>{
		public int compare(String o1, String o2) {
			int i1=CATE_ORDER.indexOf(o1);
			int i2=CATE_ORDER.indexOf(o2);
			int comp=i1-i2;
			if(comp!=0||i1>=0){
				return i1-i2;
			}
			return o1.compareTo(o2);
		}
	}
	


	/**
	 * 取得常量列表
	 * @param elemType 类型
	 * @param loc 指定的locale
	 * @return List
	 */
	public List<Object[]>getConstants(Object elemType){
		Locale loc=ThreadLocalConstants.LOCALE.get();
		if(loc==null){
			loc=Locale.getDefault();
		}
		if(Utils.isEmpty(CONTANT_LIB)){
			init(AdaptorManager.getInstance().getCompInfo(),loc);
		}
		return CONTANT_LIB.get(elemType);
	}
	/**
	 * 取得候选项列表
	 * @param elemType 类型
	 * @param loc 指定的locale
	 * @return List
	 */
	public List<Object[]>getOptions(Object elemType){
		org.springframework.web.servlet.i18n.LocaleChangeInterceptor a;
		Locale loc=ThreadLocalConstants.LOCALE.get();
		if(loc==null){
			loc=Locale.getDefault();
		}
		Map<Object,List<Object[]>> OPTION_LIB=OPTION_LIBS.get(loc);
		if(OPTION_LIB==null){
			init(AdaptorManager.getInstance().getCompInfo(),loc);
			OPTION_LIB=OPTION_LIBS.get(loc);
		}
		return OPTION_LIB.get(elemType);
	}
	private Map<Locale,Map<Object,List<Object[]>>> OPTION_LIBS=new HashMap<Locale,Map<Object,List<Object[]>>>();
	private Map<Object, List<Object[]>> CONTANT_LIB= new HashMap<Object,List<Object[]>>();
	private void init(ComponentInfo i,Locale loc){
		Map<Object, List<Object[]>> OPTION_LIB= new HashMap<Object,List<Object[]>>();
		OPTION_LIBS.put(loc,OPTION_LIB);
		OPTION_LIB.put(ELEM_TYPE_BOOLEAN, Arrays.asList(new Object[][]{
				{"1",i.getConstName("yes")},{"0", i.getConstName("no")},{null, i.getConstName("default")},
		}));
		
		List<Object[]> classLib = Arrays.asList(new Object[][]{
				//{标识、类名、页面显示要传入的字符、是否有默认选项}
				{ ELEM_TYPE_EVENT,EventTarget.class, "event.",false },
				{ ELEM_TYPE_ALIGN, Alignable.class, "align.",true },
				{ ELEM_TYPE_VALIGN,Valignable.class, "valign.",true },
				{ ELEM_TYPE_SCROLLCLASS,Scrollable.class, "scrollClass.",true },
				{ ELEM_TYPE_DATE_FORMAT,DatePicker.class, "DatePicker.",false },
				{ ELEM_TYPE_DATE_FORMAT,MuldatePicker.class, "MuldatePicker",false },
				{ ELEM_TYPE_TYPE_PAGE,PageBar.class, "page.",false },
				{ ELEM_TYPE_TYPE_CALENDAR,CalendarPanel.class, "calendar.",false },
				{ ELEM_TYPE_TYPE_TRIPLEBOX,Triplebox.class, "triplebox.",true },
				{ ELEM_TYPE_TYPE_GRIDLAYOUT,AbstractGridLayout.class, "gridLayout.",true },
				{ ELEM_TYPE_TYPE_GRIDCOLUMN,GridColumn.class, "gridColumn.",false },
				{ ELEM_TYPE_TYPE_DIALOGWIDTH,DialogWidth.class, "dialogWidth.",false },
				{ ELEM_TYPE_TYPE_DIALOGHEIGHT,DialogHeight.class, "dialogHeight.",false },
				{ ELEM_TYPE_TYPE_PATTERN,Pattern.class, "pattern.",true },
				{ ELEM_TYPE_TYPE_SUBMITCOMMAND,SubmitCommand.class, "submitCommand.",false },
				{ ELEM_TYPE_TYPE_BUTTONBAR,ButtonBar.class, "buttonBar.",true },
		});
		//加载事件候选项
		//{ ELEM_TYPE_EVENT,EventTarget.class, "event.",false },
		for(Object[] lib:classLib){
			List<Object[]> classOptions=new ArrayList<Object[]>();
			List<Object[]> classContants=new ArrayList<Object[]>();
			for(Field f: ((Class<?>) lib[1]).getDeclaredFields()){
				if(Modifier.isPublic(f.getModifiers())&&Modifier.isStatic(f.getModifiers())&&Modifier.isFinal(f.getModifiers())){
					try {
						Object value=f.get(null);
						String showName=(String) lib[2];//event.
						//[center, 居中(center)]
						//[yyyy-mm-dd, DATE]
						//候选值[value值，view显示在页面上的值]
						if(DatePicker.class==lib[1]||MuldatePicker.class==lib[1]){
							classOptions.add(new Object[]{value,value });
						}else{
							classOptions.add(new Object[]{value,i.getConstName(showName+value) });
						}
						//常量值[value值，产生javaCode的常量后面.的字符:DATE]
						classContants.add(new Object[]{String.valueOf(value),f.getName() });
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
			if((Boolean) lib[3]){
				classOptions.add(new Object[]{null, i.getConstName("default")});
			}
			OPTION_LIB.put(lib[0], classOptions);
			CONTANT_LIB.put(lib[0], classContants);
		}
	}
	public static final Object ELEM_TYPE_BOOLEAN=new Object();
	public static final Object ELEM_TYPE_BOOLEAN_NOT_NULL=new Object();
	
	public static final Object ELEM_TYPE_ALIGN=new Object();
	public static final Object ELEM_TYPE_VALIGN=new Object();
	public static final Object ELEM_TYPE_SCROLLCLASS=new Object();
	public static final Object ELEM_TYPE_EVENT=new Object();
	public static final Object ELEM_TYPE_DATE_FORMAT=new Object();
	public static final Object ELEM_TYPE_TYPE_PAGE=new Object();
	public static final Object  ELEM_TYPE_TYPE_CALENDAR=new Object();

	public static final Object  ELEM_TYPE_TYPE_TRIPLEBOX=new Object();
	public static final Object  ELEM_TYPE_TYPE_GRIDLAYOUT=new Object();
	public static final Object  ELEM_TYPE_TYPE_GRIDCOLUMN=new Object();
	public static final Object  ELEM_TYPE_TYPE_DIALOGWIDTH=new Object();
	public static final Object  ELEM_TYPE_TYPE_DIALOGHEIGHT=new Object();
	public static final Object  ELEM_TYPE_TYPE_SUBMITCOMMAND=new Object();
	public static final Object  ELEM_TYPE_TYPE_PATTERN=new Object();
	public static final Object  ELEM_TYPE_TYPE_BUTTONBAR=new Object();

	public void sortViewNodesByGroups(List<DfishViewNode> viewNodes) {
		List<ViewNodeExt> parseInfo=parseInfo(viewNodes);
		Collections.sort(parseInfo,new Comparator<ViewNodeExt>(){
			@Override
			public int compare(ViewNodeExt o1, ViewNodeExt o2) {
				if(o1==o2){
					return 0;
				}
				int i1=getComponentGroup(o1);
				int i2=getComponentGroup(o2);
				return i1-i2;
			}

			private int getComponentGroup(ViewNodeExt o1) {
				if(o1.getCompData()!=null){
					String mode= o1.getCompData().getMode();
					if(mode!=null&&mode.startsWith("<")){
						return 10;
					}
					if(mode!=null&&mode.startsWith("[")){
						return 20;
					}
				}

				return getTypeSortOrder(o1.getCompData().getType());
			}
		});
		viewNodes.clear();
		viewNodes.addAll(parseInfo);
	}
	
	public static List<ViewNodeExt> parseInfo(List<DfishViewNode> viewNodes) {
		if(viewNodes==null){
			return null;
		}
		List<ViewNodeExt>  result=new ArrayList<ViewNodeExt>(viewNodes.size());
		for(DfishViewNode n:viewNodes){
			if(n instanceof ViewNodeExt){
				result.add((ViewNodeExt)n);
			}else{
				ViewNodeExt vne=new ViewNodeExt();
				Utils.copyPropertiesExact(vne, n);
				vne.setCompData(AdaptorManager.parseData(n));
				result.add(vne);
			}
		}
		return result;
	}

	public static class ViewNodeExt extends DfishViewNode{
		private ComponentData compData;

		public ComponentData getCompData() {
			return compData;
		}

		public void setCompData(ComponentData compData) {
			this.compData = compData;
		}
	}

	public List<String> getAllTypes() {
		return new ArrayList<String>(this.adaptors.keySet());
	}
	/**
	 * 从class中获得PropertyDefine
	 * 
	 * @return List
	 */
	public static List<PropertyDefine> loadPropDefine(Class<?>clz) {
		//FIXME 还要提供其他组件的默认值
		//FIXME GridColumn等部分组件包含后端专有的dataFormat属性。

		List<PropertyDefine> result = new ArrayList<PropertyDefine>();
		// 我们从class中读取属性。
		JsonBuilder b = J.get(clz);
		String typeName = BeanUtil.getClassShortName(clz.getName());
		ClassJsonBuilder cjb = (ClassJsonBuilder) b;
		for (JsonBuilderProperGetter getter : cjb.getMethods()) {
			if (
					"data".equals(getter.getPropName()) || "on".equals(getter.getPropName()) || 
					"validate".equals(getter.getPropName()) || "validategroup".equals(getter.getPropName()) || 
					"prototype".equals(getter.getPropName()) || "nodes".equals(getter.getPropName()) || 
					"node".equals(getter.getPropName()) || "templates".equals(getter.getPropName()) || 
					"commands".equals(getter.getPropName()) ||  "targets".equals(getter.getPropName()) || 
					"hiddens".equals(getter.getPropName()) ||"pub".equals(getter.getPropName())) {
				//子属性不在编辑面板中展现，而在机构树上展现
				continue;
			}
			if("type".equals(getter.getPropName()) ){// type属性一般不在编辑面板中体现，部分例外 如一些 控制命令。
				if("PagePanel".equals(typeName)||"CalendarPanel".equals(typeName)){
					//这几类需要设置TYPE
				}else{
					continue;
				}
			}
			PropertyDefine define = new PropertyDefine();
			result.add(define);
			//FORM表单 name 必填
			if("name".equals(getter.getPropName())){
				if(FormElement.class.isAssignableFrom(clz)){
					define.setRequired(true);
				}
			}
			//处理必填和默认值
			if("id".equals(getter.getPropName())){
				if("FormPanel".equals(typeName)){
					define.setRequired(true);
					define.setDefaultValue("form");
				}else if("GridPanel".equals(typeName)){
					define.setRequired(true);
					define.setDefaultValue("grid");
				}else if("TreePanel".equals(typeName)){
					define.setRequired(true);
					define.setDefaultValue("tree");
				}else if("ButtonBar".equals(typeName)){
					define.setRequired(true);
					define.setDefaultValue("btn");
				}else if("PagePanel".equals(typeName)){
					define.setRequired(true);
					define.setDefaultValue("page");
				}
			}else if("src".equals(getter.getPropName())){
				if("Combobox".equals(typeName)){
					define.setRequired(true);
				}
			}else if("name".equals(getter.getPropName())){

			}
			//功能板面板ID必填
			
			//功能面板ID给个默认值
			
		
			define.setName(getter.getPropName());
			
			define.setType(BeanUtil.getClassShortName(BeanUtil.getRealReturnType(getter.getGetterMethod(),clz).getName()));
		}
		return result;
	}


}


